package org.virbraligo.vboxjavaservice.gui;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.virbraligo.vboxjavaservice.VBoxJavaService;
import org.virbraligo.vboxjavaservice.gui.validator.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

//http://www.krenger.ch/blog/tag/java-service-wrapper/
public class AdminFrame extends JFrame {
	public static final File CONFIG_DIR = new File(System.getProperty(
			"conf.dir", "wrapperservice"));

	public static final File DEGFAULT_CONFIG_FILE = new File(
			CONFIG_DIR.getAbsolutePath() + File.separator
					+ "sample.wrapper.conf");

	private Document confModelDoc = null;

	private File[] confFiles;

	private JTabbedPane tabPane = new JTabbedPane();

	private String firstServiceSplit;

	private String[] services;

	private static AdminFrame adminFrame;

	private AdminFrame() {
		setTitle("VBoxJavaService Config");
		readConfig();
		init();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(600, 300);
		setLocation(300, 100);
		setIconImage(new ImageIcon(getClass().getResource(
				"virtualbox-vbox-48px.png")).getImage());
	}

	public static AdminFrame getInstance() {
		if (adminFrame == null) {
			adminFrame = new AdminFrame();
		}
		return adminFrame;
	}

	private void readConfig() {
		confFiles = CONFIG_DIR.listFiles(new FilenameFilter() {

			public boolean accept(File dir, String name) {
				return name.startsWith("wrapper.conf.");
			}
		});
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder bulider = factory.newDocumentBuilder();
			confModelDoc = bulider.parse(AdminFrame.class.getResource(
					"/conf_model.xml").getFile());

		} catch (Exception e) {
			e.printStackTrace();

		}
		try {
			String serviceContent = VBoxJavaService
					.execute("sc query state= all");
			services = serviceContent.split("\n");
			firstServiceSplit = "SERVICE_NAME";
			for (int i = 0; i < services.length; i++) {
				if (services[i].length() > 0 && !services[i].equals("\r")) {
					firstServiceSplit = services[i].split(":")[0].trim();
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void init() {
		BorderLayout layout = new BorderLayout(5, 5);
		getContentPane().setLayout(layout);
		JMenuBar menuBar = new JMenuBar();
		JMenu fileMenu = new JMenu("File");
		menuBar.add(fileMenu);
		JMenuItem createServiceItem = new JMenuItem("New Service");
		createServiceItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				showServiceConfig(DEGFAULT_CONFIG_FILE);
				tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
			}

		});
		fileMenu.add(createServiceItem);
		JMenuItem exitItem = new JMenuItem("Quit");
		exitItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		fileMenu.add(exitItem);
		getContentPane().add(menuBar, BorderLayout.NORTH);
		getContentPane().add(tabPane, BorderLayout.CENTER);
		// tabPane.setTitleAt(index, title)

		if (confFiles == null || confFiles.length == 0) {
			showServiceConfig(DEGFAULT_CONFIG_FILE);
		} else {
			for (int i = 0; i < confFiles.length; i++) {
				showServiceConfig(confFiles[i]);
			}
		}
		JPanel buttonPanel = new JPanel();
		GridBagLayout gl = new GridBagLayout();
		buttonPanel.setLayout(gl);
		GridBagConstraints cons = new GridBagConstraints();
		cons.insets = new Insets(3, 10, 6, 3);
		JButton installBtn = new JButton("Install Service");
		JButton uninstallBtn = new JButton("Unnstall Service");
		JLabel empty = new JLabel();
		JButton closeBtn = new JButton("Close");
		cons.gridx = 0;
		buttonPanel.add(installBtn, cons);
		cons.gridx++;
		buttonPanel.add(uninstallBtn, cons);
		cons.gridx++;
		cons.weightx = 1;
		buttonPanel.add(empty, cons);
		cons.gridx++;
		cons.weightx = 0;
		buttonPanel.add(closeBtn, cons);
		getContentPane().add(buttonPanel, BorderLayout.SOUTH);
		installBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				installService();
			}
		});
		uninstallBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				uninstallService();
			}
		});
		closeBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

	}

	private void installService() {
		ServicePanel panel = (ServicePanel) tabPane.getSelectedComponent();
		panel.installService();
	}

	private void uninstallService() {
		ServicePanel panel = (ServicePanel) tabPane.getSelectedComponent();
		panel.uninstallService();
	}

	private void showServiceConfig(File configFile) {
		try {
			List configurations = loadServiceProperties(configFile);
			ServicePanel panel = new ServicePanel(tabPane, configurations,
					configFile);
			tabPane.addTab(panel.getPanelName(), panel);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public String getFirstServiceSplit() {
		return firstServiceSplit;
	}

	public String[] getServices() {
		return services;
	}

	private List loadServiceProperties(File confFile) throws IOException {
		String validatorPackage = Validator.class.getPackage().getName();
		InputStream in = new FileInputStream(confFile);
		Properties p = new Properties();
		p.load(in);
		in.close();
		List configList = new ArrayList();
		NodeList nodes = confModelDoc.getElementsByTagName("conf");
		for (int i = 0; i < nodes.getLength(); i++) {
			Element e = (Element) nodes.item(i);
			Config conf = new Config();
			conf.setLabelName(e.getAttribute("labelName"));
			conf.setTooltip(e.getAttribute("tooltip"));
			conf.setWrapperConfPropertyName(e
					.getAttribute("wrapperConfPropertyName"));
			String propname = conf.getWrapperConfPropertyName();
			String value = p.getProperty(propname);
			if (propname.startsWith("wrapper.app.parameter")) {
				conf.setValue(value.replaceAll("\"", ""));
			} else {
				conf.setValue(value);
			}
			String validatorClass = e.getAttribute("validator");
			if(validatorClass == null || "".equals(validatorClass)){
				validatorClass = "NotEmptyValidator";
			}
			if (!validatorClass.contains(".")) {
				validatorClass = validatorPackage + "." + validatorClass;
			}
			try {
				Validator validator = (Validator) Class.forName(validatorClass)
						.newInstance();
				conf.setValidator(validator);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			configList.add(conf);
		}
		return configList;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager
							.getSystemLookAndFeelClassName());
				} catch (Exception e) {
					e.printStackTrace();
				}
				AdminFrame.getInstance().setVisible(true);
			}
		});
	}

}
